package semantic.analyzer;

import java.util.List;

import metamodel.Attribute;
import metamodel.MetamodelManager;
import metamodel.Method;
import metamodel.MyClass;
import semantic.SemanticException;
import semantic.model.Context;

public class OperationContextAnalyzer {

	private static MetamodelManager metamodelManager = MetamodelManager.getInstance();
	
	public static Context context;
	
	public static void checkPath(String pathName, List<Attribute> parameters, String returnType) {
		String[] path = pathName.split("::");
		if (path.length >= 2) {
			MyClass klass = metamodelManager.getClass(path[path.length - 2]);
			checkCompletely(path, klass, parameters, returnType);
		} else {
			throw new SemanticException("Invalid operation context.");
		}
	}

	private static void checkCompletely(String[] path, MyClass klass, List<Attribute> parameters, String returnType) {
		if (klass == null) {
			throw new SemanticException("Class '" + path[path.length - 2] + "' does not exist.");
		}

		Method method = klass.getMethod(path[path.length - 1]);
		if (method == null) {
			throw new SemanticException("Class '" + klass.getName() + "' does not implement '" + path[path.length - 1]  + "' method");
		}
		checkParametersOrder(method, parameters);
		checkReturnType(method, returnType);
		context = new Context(klass, method, method.getParameters());
	}
	
	private static void checkReturnType(Method method, String returnType) {
		String originalReturnType = method.getReturnType();
		if (!originalReturnType.equals(returnType)) {
			throw new SemanticException("Invalid return type on method " + method.getName());
		}
	}

	private static void checkParametersOrder(Method method, List<Attribute> parameters) {
		List<Attribute> originalParameters = method.getParameters();
		if (originalParameters.size() != parameters.size()) {
			throw new SemanticException("Incorrect number of parameters on method '" + method.getName() + "'");
		}
		for (int i = 0; i < originalParameters.size(); i++) {
			String originalParameterType = originalParameters.get(i).getType();
			String parameterType = parameters.get(i).getType();
			if (!originalParameterType.equals(parameterType)) {
				throw new SemanticException("Incorrect parameters on method '" + method.getName() + "'");
			}
		}
	}
}
